#include "openglwidget.h"
#include <QDebug>

OpenGLWidget::OpenGLWidget(QWidget *parent) : QOpenGLWidget(parent),
    m_translation(0, 0, 0),
    m_rotation(),
    m_scale(1.0f),
    m_bboxMin(-1, -1, -1),
    m_bboxMax(1, 1, 1)
{
    setMouseTracking(true);
}

OpenGLWidget::~OpenGLWidget()
{
}

void OpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glEnable(GL_DEPTH_TEST);
}

void OpenGLWidget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
    m_projection.setToIdentity();
    m_projection.ortho(float(w) / h * -10, float(w)/h * 10, -10, 10, -100, 100);
}

void OpenGLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    m_view.setToIdentity();
    m_view.translate(m_translation);
    m_view.rotate(m_rotation);
    m_view.scale(m_scale);

    // 应用投影矩阵
    glMatrixMode(GL_PROJECTION);
    glLoadMatrixf(m_projection.data());

    // 应用模型视图矩阵
    glMatrixMode(GL_MODELVIEW);
    glLoadMatrixf(m_view.data());

    drawCube();
}

void OpenGLWidget::mousePressEvent(QMouseEvent *event)
{
    m_lastMousePos = event->pos();
}

void OpenGLWidget::mouseMoveEvent(QMouseEvent *event)
{
    QPoint delta = event->pos() - m_lastMousePos;
    m_lastMousePos = event->pos();
    if (event->buttons() & Qt::LeftButton) {


        QQuaternion rotX = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, delta.y());
        QQuaternion rotY = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, delta.x());
        m_rotation = rotX * rotY * m_rotation;

    }else if(event->buttons() & Qt::MiddleButton) {
        float sensitivity = 20.0f / qMin(width(), height());
        m_translation += QVector3D(delta.x() * sensitivity, -delta.y() * sensitivity, 0);
    }

    update();
}

void OpenGLWidget::wheelEvent(QWheelEvent *event)
{
    QPointF mousePos = event->position().toPoint();

    // 1. 计算鼠标位置的NDC坐标
    QVector2D ndcPos(
        2.0f * mousePos.x()/width() - 1.0f,
        1.0f - 2.0f * mousePos.y()/height()
        );

    // 2. 计算当前鼠标在世界坐标系中的位置
    float visibleWidth = 20 * float(width())/height();
    float visibleHeight = 20;
    QVector3D mouseWorldPos(
        (ndcPos.x() * visibleWidth/2.0f - m_translation.x()) / m_scale,
        (ndcPos.y() * visibleHeight/2.0f - m_translation.y()) / m_scale,
        0
        );

    // 3. 应用缩放因子
    float zoomFactor = 1.0f + event->angleDelta().y() * 0.001f;
    float newScale = qBound(0.1f, m_scale * zoomFactor, 10.0f);

    // 4. 计算平移补偿量（核心修正）
    QVector3D offset = mouseWorldPos * (1.0f/m_scale - 1.0f/newScale);

    // 5. 更新变换参数
    m_translation += offset;
    m_scale = newScale;

    update();
}

void OpenGLWidget::zoomFit()
{
    // Calculate bounding box center and size
    QVector3D center = (m_bboxMin + m_bboxMax) * 0.5f;
    QVector3D size = m_bboxMax - m_bboxMin;
    float maxSize = qMax(size.x(), qMax(size.y(), size.z()));

    // Reset transformations
    m_translation = -center;
    m_scale = 10.0f / maxSize;

    update();
}

void OpenGLWidget::drawCube()
{
    glBegin(GL_QUADS);
    // Front face
    glColor3f(1.0f, 0.0f, 0.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);

    // Back face
    glColor3f(0.0f, 1.0f, 0.0f);
    glVertex3f(1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);

    // Top face
    glColor3f(0.0f, 0.0f, 1.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(1.0f, 1.0f, -1.0f);

    // Bottom face
    glColor3f(1.0f, 1.0f, 0.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);

    // Right face
    glColor3f(1.0f, 0.0f, 1.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);
    glVertex3f(1.0f, 1.0f, -1.0f);

    // Left face
    glColor3f(0.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glEnd();
}
